package com.lj.common_web.request;

import cn.hutool.extra.spring.SpringUtil;
import com.lj.common_web.annotation.RequestBodyDecrypt;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.core.MethodParameter;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpInputMessage;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter;

import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Type;

/**
 * @author luojing
 * @since 2025/5/29 18:08
 * 请求体需要解密处理
 */
@RestControllerAdvice
@ConditionalOnBean(RequestBodyDecipher.class)
public class RequestControllerAdvice extends RequestBodyAdviceAdapter {

    @Override
    public boolean supports(MethodParameter methodParameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) {
        RequestBodyDecrypt annotation = getAnnotation(methodParameter);
        return annotation != null && annotation.value();
    }

    @Override
    public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class<? extends HttpMessageConverter<?>> converterType) throws IOException {
        RequestBodyDecrypt annotation = getAnnotation(parameter);
        RequestBodyDecipher decipher = SpringUtil.getBean(annotation.decipher());
        return new HttpInputMessage() {
            @Override
            public InputStream getBody() throws IOException {
                return decipher.decrypt(inputMessage, parameter, annotation);
            }

            @Override
            public HttpHeaders getHeaders() {
                return inputMessage.getHeaders();
            }
        };
    }


    private RequestBodyDecrypt getAnnotation(MethodParameter methodParameter) {
        //判断方法上是否有目标注解
        RequestBodyDecrypt methodAnnotation = methodParameter.getMethodAnnotation(RequestBodyDecrypt.class);
        if (methodAnnotation != null) {
            return methodAnnotation;
        }
        //判断类上是否有目标注解
        return methodParameter.getDeclaringClass().getAnnotation(RequestBodyDecrypt.class);
    }

}
